using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using SNFEGame.Menus;
using SNFEGame.Util;
using SNFEGame.Visual;
using SNFEGame.States;

/*
 * Brian Clanton
 * Kyler Connare
 * Alex Mancillas
 * Derin Yarsuvat
 * 
 * RIT ImagineCup 2011
 */
namespace SNFEGame
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class MainGame : Microsoft.Xna.Framework.Game
    {
        private GraphicsDeviceManager graphics;
        private SpriteBatch spriteBatch;

        private static Viewport defaultViewport;

        private static bool applicationClosed = false;

        public static int Width
        {
            get { return GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width; }
        }

        public static int Height
        {
            get { return GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height; }
        }

        private static int fps;
        private static int totalFrames;
        private static float elapsedTime;
        private static bool showingFps = false;
        private static ContentManager content;

        private static bool pressedDown = false;

        private static BaseState currentState;
        //private static MainMenuState mainMenuState;
        //private static GameState gameState;

        private static BaseState CurrentState
        {
            get
            {
                return currentState;
            }
            set
            {
                if (currentState != null)
                    currentState.SetActive(false);

                currentState = value;
                currentState.SetActive(true);
            }
        }

        public MainGame()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferWidth = Width;
            graphics.PreferredBackBufferHeight = Height;
            graphics.IsFullScreen = true;
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            Storage.Initialize(Content);
            content = Content;
            //mainMenuState = new MainMenuState();
            //gameState = new GameState();

            currentState = new MainMenuState();

            defaultViewport = graphics.GraphicsDevice.Viewport;

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (applicationClosed)
                this.Exit();

            float deltaT = (float)gameTime.ElapsedGameTime.TotalSeconds;
            elapsedTime += (float)gameTime.ElapsedGameTime.TotalMilliseconds;

            if (elapsedTime >= 1000f)
            {
                fps = totalFrames;
                totalFrames = 0;
                elapsedTime = 0;
            }

            /// handling keyboard input while in game
            #region keyboard input
            /// Toggle debug with 'd'
            if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.D))
            {
                if (!pressedDown)
                {
                    pressedDown = true;
                    showingFps = !showingFps;

                    if (CurrentState is GameState)
                        (CurrentState as GameState).ToggleBoundsDrawn();
                }
            }
            else
                {
                    pressedDown = false;
                }

            #endregion

            CurrentState.Update(deltaT);

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            totalFrames++;
            GraphicsDevice.Clear(Color.White);
            graphics.GraphicsDevice.Viewport = defaultViewport;

            CurrentState.Draw(spriteBatch);

            spriteBatch.Begin();
            // Write fps to screen
            if (showingFps)
                spriteBatch.DrawString(Storage.GetFont("Terminal"), "fps: " + fps, new Vector2(10f, 10f), Color.LimeGreen);
            spriteBatch.End();

            base.Draw(gameTime);
        }

        public static void CloseApplication()
        {
            applicationClosed = true;    
        }

        public static void GoToMainMenu()
        {
            CurrentState = new MainMenuState();
        }

        public static void GoToGame()
        {
            CurrentState = new GameState(content, defaultViewport);
            if (showingFps)
                (CurrentState as GameState).ToggleBoundsDrawn();
        }
    }
}